
// WallClipper.h

// Interfaces to the cWallClipper class that performs wall-clipping of a cube moving through a cBlockArea




// fwd: BlockArea.h
class cBlockArea;





class cWallClipper
{
public:

	/// Flags which walls were hit
	enum eHitWall
	{
		hwNone,   // Didn't hit any wall
		hwX = 1,  // Hit a wall in the X direction
		hwY = 2,  // Hit a wall in the Y direction
		hwZ = 4,  // Hit a wall in the Z direction
	} ;
	
	/** Checks a cube at a_Pos (min coords) of the specified size if it can fit through a_Area for the entire a_Direction.
	If there's a wall in the way, it clips a_Direction and returns the wall(s) that have been hit (using ORed eHitWall enums)
	*/
	static int Do(const Vector3d & a_Pos, double a_SizeX, double a_SizeY, double a_SizeZ, Vector3d & a_Direction, const cBlockArea & a_Area);
	
	static bool IsBlockPassable(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
	
protected:
	cWallClipper(const Vector3d & a_Pos, double a_SizeX, double a_SizeY, double a_SizeZ, Vector3d & a_Direction, const cBlockArea & a_Area);
	
	/// The internals of the static Do(), same return value
	int Do(void);
	
	/** Checks all 3 walls, returns eHitWall combination of the hit walls.
	a_Pos is always the lower coords of the checked cube, use m_WallXOffset to get real X wall coord.
	Also clips m_Direction by all the walls returned.
	*/
	int CheckWalls(int a_PosX, int a_PosY, int a_PosZ);
	
	/// Returns hwX and clips m_Direction if X wall hit; returns hwNone otherwise
	int CheckXWall(int a_PosX, int a_PosY, int a_PosZ);

	/// Returns hwY and clips m_Direction if Y wall hit; returns hwNone otherwise
	int CheckYWall(int a_PosX, int a_PosY, int a_PosZ);

	/// Returns hwZ and clips m_Direction if Z wall hit; returns hwNone otherwise
	int CheckZWall(int a_PosX, int a_PosY, int a_PosZ);
	
	/// Clips m_Direction so that each of its axes is smaller (in absolute value) than the values specified
	void ClipDirection(double a_ClipX, double a_ClipY, double a_ClipZ);

	
	const Vector3d & m_Pos;
	
	double m_SizeX;
	double m_SizeY;
	double m_SizeZ;
	
	Vector3d & m_Direction;
	
	const cBlockArea & m_Area;
	
	int m_WallSizeX;  ///< m_SizeX, rounded up to the nearest integer
	int m_WallSizeY;  ///< m_SizeY, rounded up to the nearest integer
	int m_WallSizeZ;  ///< m_SizeZ, rounded up to the nearest integer

	int m_WallXOffset;  ///< Offset of the wall in the X direction (YZ plane) where it should be checked. Zero for negative-X direction, SizeX for positive-X direction
	int m_WallYOffset;  ///< Offset of the wall in the Y direction (XZ plane) where it should be checked. Zero for negative-Y direction, SizeY for positive-Y direction
	int m_WallZOffset;  ///< Offset of the wall in the Z direction (XY plane) where it should be checked. Zero for negative-Z direction, SizeZ for positive-Z direction
} ;




